Day7的練習答案:
Try1:請計算2019.05.28到 2020.09.08過了多少日期。
let dat1 = new Date(2020,09,08);
let dat2 = new Date(2019,05,28);
let diff = (dat1.getTime()-dat2.getTime())/(1000*60*60*24);
console.log(diff); //468
基本上就是將Day7例子中的日期換掉就好!
今天開始進入函式囉!
什麼是函式? 不知道大家記不記得再Day4的時候有稍微提到 "函式是將某些輸入值(參數),已預先設定好的程序處理後,再回傳結果。"
那為什麼我們需要他呢? 常常我們會有一段或多段程式需要重複利用,這時候我們就可以用函式將它包裝起來,有需要用的時候就呼叫那個函式。
宣告方法等等介紹,但不管甚麼方式,都會包含幾個部分:
// First 用function指令定義
function myFun(base, height){
return (base * height)/2;
};
console.log('Ans:'+ myFun(20,10)); // Ans:100
//將 20 與 10帶入myFun
//執行 return (base + height)/2
// Second 用Function建構子定義
let myFun2 = new Function('base','height','return base * height/2');
console.log('Ans2:' + myFun2(20,10)); //Ans:100
//將程式用Function建構子來寫,但可讀性較差
//Third 用函式常值定義
let myFun3 = function(base, height){
return (base * height)/2
}
console.log('Ans3:' + myFun3(20,10)); // Ans:100
//Forth 箭頭函式 ES6才出現
let myFun4 = (base,height) => base * height /2;
console.log('Ans4:' + myFun4(20,10)); // Ans:100
接下來比較一下四種在執行上的差別
// First 用function指令定義
console.log('Ans:'+ myFun(20,10)); // Ans:100
function myFun(base, height){
return (base * height)/2;
};
// Second 用Function建構子定義
console.log('Ans2:' + myFun2(20,10)) //Ans:報錯:
//Uncaught ReferenceError: Cannot access 'myFun2' before initialization
let myFun2 = new Function('base','height','return base * height/2');
//Third 用函式常值定義
console.log('Ans3:' + myFun3(20,10)) // Ans:報錯
//Uncaught ReferenceError: Cannot access 'myFun3'
let myFun3 = function(base, height){
return (base * height)/2;
};
// //Forth 箭頭函式 ES6才出現
console.log('Ans4:' + myFun4(20,10)) //Ans:報錯:
//Uncaught ReferenceError: Cannot access 'myFun2' before initialization
let myFun4 = (base,height) => base * height /2;
透過上述四種寫法,我們發現只有第一種function指令定義不會報錯,原因在於,其他三種都是在執行時才會解析,所以當我們將console.log('Ans:' + myFun(20,10))
這段放到函式前時,就會出錯。
簡單來說就是全域變數與區域變數的差別,先簡單描述一下:
接著我們透過程式碼來解說:
let x = 10; //全域變數
function getValue(){
let x = 100; //區域變數
return x;
};
console.log(getValue()); //100
console.log(x); //10
透過上述的例子我們了解了,當我們執行了 console.log(getValue());
,他會將函式內的區域變數(let x = 100;)傳入,所以是 100。
而console.log(x);
在這段程式碼中的x為什麼不是100卻是10呢?
因為再函式內定義的let x = 100;
實際上只屬於在getValue這個涵式中,
所以當我們執行console.log(x); //10
這段的時候他是找到let x = 10;
這個x變數。
那如果function內沒有x變數呢?
let x = 10; //全域變數
function getValue(){
return x
}
console.log(getValue()); //10
console.log(x); //10
如果function內沒有對應的變數,就會往外層找,直到全域變數為止,所以得到的是10。
這邊要注意的是,function可以讀取外層以宣告的變數,但外層沒辦法讀取function內
所宣告的變數。
最後,我們將全域與區域變數以及函式的寫法合併起來觀察:
let x = 10; //全域變數
function getValue(){
let x =100; //區域變數
function myFun1(){return x;};
console.log(myFun1()); // 100
let myFun2 = function(){return x;};
console.log(myFun2()); // 100
let myFun3 = new Function('return x;');
console.log(myFun3()); // 10
let myFun4 = () => x;
console.log(myFun4()); // 100
}
getValue();
透過以上程式碼,我們可以發現只有在myFun3得到的結果是不同的,這是為什麼呢?
原因是當使用Function建構子來定義函式,他參考的變數會是全域變數,因此得到的結果是10,因此Function建構子除了可讀性不佳以外,還有這個缺點,盡量在使用上避免。
let x = 20;
function getValue(y){
x = 30;
return x+y;
}
console.log(getValue(10));
console.log(x);
求:呼,今天告一個段落囉,後續的文章如果可以都會用程式碼做解釋,除了加深我自己的印象之外,也希望大家可以動手做囉~ 明天見!